/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.edu.cs576.HyperLinkVideo.authoringtool;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import javax.swing.event.MouseInputAdapter;

/**
 * Handles keyframe size,position modification, etc.
 *
 * @author Ludo
 */
public class TrackingAreaHandler extends MouseInputAdapter {

    //points listed in clockwise order around rectangle
    private int[] xPoints;
    private int[] yPoints;
    private TrackingArea currentArea;
    private PrimaryVideoViewPanel panel;
    private int panelWidth;
    private int panelHeight;
    private int[] initialClick;
    private boolean moving;
    private boolean resizing;
    
    private final int north = 1;
    private final int east = 2;
    private final int south = 3;
    private final int west = 4;
    
    private int currentSelectedEdge;

    public TrackingAreaHandler(PrimaryVideoViewPanel panel) {
        this.panel = panel;
        panel.addMouseMotionListener(this);
        panel.addMouseListener(this);
        moving = false;
        resizing = false;
        currentSelectedEdge = 0;
    }
    
    public void removeHandler(){
        this.deleteRect();
        panel.removeMouseListener(this);
        panel.removeMouseMotionListener(this);
        panel = null;
        moving = false;
        resizing = false;
        currentSelectedEdge = 0;        
    }

    /**
     * Adds a rectangle of default size, centered in the VideoViewPanel
     */
    public void addDefaultRect() {
        Dimension d = panel.getSize();
        panelWidth = d.width;
        panelHeight = d.height;
        int width = d.width / 3;
        int height = d.height / 3;
        xPoints = new int[4];
        yPoints = new int[4];
        xPoints[0] = 0;
        xPoints[1] = width;
        xPoints[2] = width;
        xPoints[3] = 0;
        yPoints[0] = 0;
        yPoints[1] = 0;
        yPoints[2] = height;
        yPoints[3] = height;
        currentArea = new TrackingArea(xPoints, yPoints);
        panel.setCurrentTrackArea(currentArea);
    }

    public void deleteRect() {
        panel.setCurrentTrackArea(null);
        currentArea = null;
    }
    
    public void setTrackingArea(TrackingArea area){
        currentArea = area;
        xPoints = area.getXPoints();
        yPoints = area.getYPoints();
    }

    /**
     * Changes the location of the Rectangle by a difference of x and y.
     */
    public void moveRect(int dx, int dy) {
        if (xPoints[0] + dx >= 0 && xPoints[2] + dx <= panelWidth) {
            if (yPoints[0] + dy >= 0 && yPoints[3] + dy <= panelHeight) {
                for (int i = 0; i < xPoints.length; i++) {
                    xPoints[i] += dx;
                    yPoints[i] += dy;
                }
                currentArea.setXPoints(xPoints);
                currentArea.setYPoints(yPoints);
                panel.setCurrentTrackArea(currentArea);
            }
        }

    }

    /**
     * Depending on the current selected edge, its two vertices are
     * added dx or dy.
     * @param diff 
     */
    public void resizeRect(int dx, int dy) {
        if(currentSelectedEdge == north){
            //only y0 and y1 move
            if(yPoints[0] + dy < yPoints[3]){
                yPoints[0] += dy;
                yPoints[1] += dy;
            }
        }else if(currentSelectedEdge == south){
            //y3 and y2
            if(yPoints[3] + dy > yPoints[0]){
                yPoints[3] += dy;
                yPoints[2] += dy;
            }
        }else if(currentSelectedEdge == east){
            //x1 and x2
            if(xPoints[1] + dx > xPoints[0]){
                xPoints[1] += dx;
                xPoints[2] += dx;
            }            
        }else if(currentSelectedEdge == west){
            //x0 x3
            if(xPoints[0] + dx < xPoints[1]){
                xPoints[0] += dx;
                xPoints[3] += dx;
            }
        }
        currentArea.setXPoints(xPoints);
        currentArea.setYPoints(yPoints);
        panel.setCurrentTrackArea(currentArea);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (isMouseWithinTrackingArea(e.getX(), e.getY())) {
            moving = true;
            initialClick = new int[]{e.getX(), e.getY()};
            panel.setCursor(new Cursor(Cursor.MOVE_CURSOR));
        } else if (isMouseOnEdge(e.getX(), e.getY()) >= 1) {
            resizing = true;
            initialClick = new int[]{e.getX(), e.getY()};
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (moving) {
            //moving rectangle
            if (isMouseWithinTrackingArea(e.getX(), e.getY())) {
                moveRect(e.getX() - initialClick[0], e.getY() - initialClick[1]);
                initialClick = new int[]{e.getX(), e.getY()};
            }
        }else if(resizing){
            resizeRect(e.getX() - initialClick[0], e.getY() - initialClick[1]);
            initialClick = new int[]{e.getX(), e.getY()};
        }


    }
     @Override
    public void mouseMoved(MouseEvent e) {
        int num = isMouseOnEdge(e.getX(), e.getY());
        if (num == north) {
            panel.setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
        }else if(num == south){
            panel.setCursor(new Cursor(Cursor.S_RESIZE_CURSOR));
        }else if(num == west){
            panel.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
        }else if(num == east){
            panel.setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
        }else{
            panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        moving = false;
        resizing = false;
        panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        currentSelectedEdge = 0;
    }
    
   

    /**
     * Is the coordinate (x,y) within the tracking area?
     *
     * @param x
     * @param y
     * @return
     */
    public boolean isMouseWithinTrackingArea(int x, int y) {
        if (xPoints[0] < x && xPoints[2] > x) {
            if (yPoints[0] < y && yPoints[3] > y) {
                return true;
            }
            return false;
        }
        return false;
    }

    /**
     * checks if coordinates are on tracking area edge. Doesn't count corners
     *
     * @param x
     * @param y
     * @return
     */
    public int isMouseOnEdge(int x, int y) {
        for (int i = 0; i < xPoints.length; i++) {
            if (xPoints[i] == x) {
                //on a vertical edge
                if(i == 0){
                    currentSelectedEdge = west;
                    return west;
                }else if(i == 1){
                    currentSelectedEdge = east;
                    return east;
                }
            } else if (yPoints[i] == y) {
                //on horizontal edge
                if(i == 0){
                    currentSelectedEdge = north;
                   return north;
                }else if(i == 3){
                    currentSelectedEdge = south;
                    return south;
                }
            }
        }
        return -1;
    }
}
